/**
 * Notes: 日志缓存管理工具类
 * Ver : CCMiniCloud Framework 2.34.1 ALL RIGHTS RESERVED BY cclinux0730 (wechat)
 * Date: 2023-09-01 14:00:00 
 */

const timeUtil = require('./time_util.js');
const LogModel = require('../config/models_config').log_model;

// 日志缓存队列
const logQueue = [];
// 最大队列长度
const MAX_QUEUE_SIZE = 100;
// 自动提交时间间隔(毫秒)
const AUTO_COMMIT_INTERVAL = 30000; // 30秒
// 上次提交时间
let lastCommitTime = 0;

class LogCache {
    /**
     * 添加日志到缓存队列
     * @param {Object} logData 日志数据
     * @param {Boolean} forceCommit 是否强制提交
     */
    static async add(logData, forceCommit = false) {
        // 添加日志到队列
        logQueue.push(logData);
        
        // 强制提交或队列已满或距离上次提交超过30秒
        const now = Date.now();
        if (forceCommit || 
            logQueue.length >= MAX_QUEUE_SIZE || 
            (now - lastCommitTime > AUTO_COMMIT_INTERVAL)) {
            await LogCache.commit();
        }
    }
    
    /**
     * 批量提交日志队列
     */
    static async commit() {
        if (logQueue.length === 0) return;
        
        // 复制当前队列并清空
        const logsToCommit = [...logQueue];
        logQueue.length = 0;
        
        try {
            // 批量插入日志
            if (logsToCommit.length === 1) {
                await LogModel.insert(logsToCommit[0]);
            } else {
                await LogModel.insertBatch(logsToCommit);
            }
        } catch (error) {
            console.error('日志批量提交失败:', error);
            // 失败时回滚到队列，但限制队列大小
            if (logQueue.length + logsToCommit.length <= MAX_QUEUE_SIZE) {
                logQueue.push(...logsToCommit);
            } else {
                // 保留关键日志(系统日志和错误/致命日志)
                const criticalLogs = logsToCommit.filter(log => 
                    log.LOG_TYPE === LogModel.TYPE.SYS || 
                    log.LOG_LEVEL >= LogModel.LEVEL.ERROR
                );
                logQueue.push(...criticalLogs);
            }
        }
        
        lastCommitTime = Date.now();
    }
    
    /**
     * 清理过期日志
     */
    static async cleanExpiredLogs() {
        const now = timeUtil.time();
        
        // 查找已过期的日志
        const where = {
            LOG_EXPIRES: ['>', 0],
            LOG_EXPIRES: ['<=', now]
        };
        
        try {
            // 删除过期日志
            await LogModel.del(where, true);
        } catch (error) {
            console.error('清理过期日志失败:', error);
        }
    }
    
    /**
     * 智能清理策略
     */
    static async smartClean() {
        const now = timeUtil.time();
        
        try {
            // 查询日志总数
            const count = await LogModel.count({});
            
            // 日志总数超过阈值，执行清理
            if (count > 100000) { // 超过10万条日志
                // 清理低级别非系统日志(90天前的DEBUG和INFO日志)
                const oldLowLevelWhere = {
                    LOG_TYPE: ['!=', LogModel.TYPE.SYS],
                    LOG_LEVEL: ['<', LogModel.LEVEL.WARN],
                    LOG_ADD_TIME: ['<', now - 90*86400]
                };
                await LogModel.del(oldLowLevelWhere, true);
                
                // 清理普通日志(180天前的所有非系统日志)
                if (count > 200000) { // 超过20万条日志
                    const oldNormalWhere = {
                        LOG_TYPE: ['!=', LogModel.TYPE.SYS],
                        LOG_ADD_TIME: ['<', now - 180*86400]
                    };
                    await LogModel.del(oldNormalWhere, true);
                }
                
                // 极端情况：清理所有365天前的日志(包括系统日志)
                if (count > 500000) { // 超过50万条日志
                    const oldAllWhere = {
                        LOG_ADD_TIME: ['<', now - 365*86400]
                    };
                    await LogModel.del(oldAllWhere, true);
                }
            }
        } catch (error) {
            console.error('智能清理日志失败:', error);
        }
    }
}

module.exports = LogCache; 